using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;

using agsXMPP;
using agsXMPP.protocol.client;
using agsXMPP.protocol.iq.vcard;

using VSTalk.Engine.Core.EntitySession;
using VSTalk.Engine.Core.XmppConnection;
using VSTalk.Engine.Core.XmppUtils;
using VSTalk.Model;
using VSTalk.Tools;

namespace VSTalk.Engine.Core.ContactInfo
{
    public class ContactInfoRequest
    {
        private Client _client;
        private string _id;
        private string _jid;
        private IActionWrapper<object, IQ> _onIq;
        private TaskCompletionSource<ContactDetails> _task = new TaskCompletionSource<ContactDetails>();
        private XmppClientConnection _connection;

        public ContactInfoRequest(Client client, string jid)
        {
            _client = client;
            _jid = jid;
        }

        private static IConnectionManager ConnectionManager
        {
            get { return AppServices.Get<IConnectionManager>(); }
        }

        public Task<ContactDetails> Send()
        {
            var dispatcher = Dispatcher.CurrentDispatcher;
            var connection = ConnectionManager.GetOrCreateConnection(_client);
            _onIq = dispatcher.Wrap<object, IQ>(OnIq);
            _connection = connection.Connection;
            _connection.OnIq += _onIq.Exec;
            var iq = new VcardIq();
            iq.Type = IqType.get;
            iq.To = _jid;
            iq.From = _connection.MyJID;
            iq.Id = _id = Guid.NewGuid().ToString("N");
            _connection.Send(iq);
            return _task.Task;
        }

        private void OnIq(object arg1, IQ arg2)
        {
            if (arg2.Id != _id || arg2.Type != IqType.result)
            {
                return;
            }
            _connection.OnIq -= _onIq.Exec;
            var vcard = arg2.Vcard;
            if (vcard == null)
            {
                _task.SetResult(null);
                return;
            }
            var description = vcard.Description;
            var birthday = vcard.Birthday;
            var fullname = vcard.Fullname;
            var url = vcard.Url;
            var photoType = vcard
                    .With(vcard1 => vcard.Photo)
                    .With(p => p.GetTag("TYPE"));
            var photoBin = vcard
                    .With(vcard1 => vcard.Photo)
                    .With(p => p.GetTag("BINVAL"))
                    .With(p => p.Split('\r', '\n'))
                    .With(p => p.FirstOrDefault())
                    .With(Convert.FromBase64String);
            var conactDetails = new ContactDetails()
            {
                Fullname = fullname,
                Birthday = birthday,
                PhotoType = photoType,
                PhotoBin = photoBin,
                Description = description,
                Url =  url
            };
            _task.SetResult(conactDetails);
        }
    }
}